//
//  ViewController.m
//  MassageForward
//
//  Created by muxue on 2019/8/31.
//  Copyright © 2019 暮雪. All rights reserved.
//

#import "ViewController.h"
#import <objc/message.h>
#import "MXSon.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self methodSignature_test];
}

/** 方法决议测试 */
- (void)resolveInstanceMethod_test {
    MXSon *son = [[MXSon alloc] init];
    id obj = son;
    NSString *str = obj;
    NSLog(@">>>>字符串长度:%ld", str.length);
}

/** 偷梁换柱，快速转发 */
- (void)forwarding_test {
    MXSon *son = [[MXSon alloc] init];
    id obj = son;
    NSArray *array = obj;
    NSLog(@"数组个数:%ld", array.count);
}

/** 正常消息转发 */
- (void)forwardInvocation_test {
    MXSon *son = [[MXSon alloc] init];
    id obj = son;
    NSDictionary *dic = obj;
    NSLog(@"数组个数:%@", dic.allKeys);
}

/** 消息发送测试 */
- (void)msgSend_test {
    //    NSArray *array = [NSArray alloc];
    // 等价于
    //    NSArray *array = objc_msgSend(NSArray.class, @selector(alloc));
}

/** NSInvocation 命令行形式的方法调用测试 */
- (void)invocation_test {
    // NSInvocation 实质上是对方法调用的一个封装
    NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:"@@:@q"];
    // 接受消息对象 MXSon
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
    invocation.target = MXSon.class;
    invocation.selector = @selector(sonWithName:age:);
    NSString *name = @"小明";
    NSInteger age = 18;
    [invocation setArgument:&name atIndex:2];
    [invocation setArgument:&age atIndex:3];
    [invocation invoke];

    __autoreleasing MXSon *son = nil;
    [invocation getReturnValue:&son];
    NSLog(@"姓名:%@, 年龄:%ld", son.name, son.age);
}

/** NSMethodSignature 方法签名测试 */
- (void)methodSignature_test {
    // 从 NSString 类方法列表中通过 stringWithFormat 生成方法签名
    //    NSMethodSignature *methodSignature = [[NSString string] methodSignatureForSelector:@selector(initWithString:)];
    // 等价于
    NSMethodSignature *methodSignature = [NSString  instanceMethodSignatureForSelector:@selector(initWithString:)];
    NSLog(@"返回值类型:%s", methodSignature.methodReturnType);
    NSLog(@"frameLength：%ld", methodSignature.frameLength);
    // 参数个数
    NSInteger numberOfArguments = methodSignature.numberOfArguments;
    // 循环打印出参数类型
    for (NSInteger i = 0; i < numberOfArguments; i++) {
        NSLog(@"第%ld个参数:%s", i, [methodSignature getArgumentTypeAtIndex:i]);
    }
}
@end
